package euler.helper;

public class Rational {

	private static final PrimeHelper primeHelper = new PrimeHelper();
    public static final Rational ZERO = new Rational(0, 1);
    public static final Rational UNO = new Rational(1, 1);
    public static final Rational DOS = new Rational(2, 1);

    private final long num;
    private final long denum;

    public Rational(long num, long denum) {
        if (denum == 0) {
            throw new ArithmeticException("Division by zero");
        }

        if (num == 0) {
            num = 0;
            denum = 1;
        } else if (denum < 0){
            num = -num;
            denum = -denum;
        }

        long mcd;
        if (num < 0) {
            mcd = primeHelper.MCD(-num, denum);
        } else if (num > 0) {
            mcd = primeHelper.MCD(num, denum);
        } else {
            mcd = 1;
        }

        this.num = num/mcd;
        this.denum = denum/mcd;
    }

    public long getNum() {
        return this.num;
    }

    public long getDenum() {
        return this.denum;
    }

    public Rational inverso() {
        if (this.num == 0) {
            throw new ArithmeticException("Division by zero");
        }

        return new Rational(this.denum, this.num);
    }

    public Rational producto(Rational op) {

        if (this.num  == 0 || op.num == 0) {
            return ZERO;
        }

        long nuevoNum = this.num * op.num;
        long nuevoDenum = this.denum * op.denum;

        return new Rational(nuevoNum, nuevoDenum);
    }

    public Rational negado() {
        return new Rational(-this.num, this.denum);
    }

    public Rational suma(Rational op) {
        long nuevoNum = this.num * op.denum + this.denum * op.num;
        long nuevoDenum = this.denum * op.denum;

        return new Rational(nuevoNum, nuevoDenum);
    }

    @Override
    public String toString() {
        if (this.denum == 1) {
            return String.valueOf(this.num);
        } else {
            return String.valueOf(this.num) + '/' + String.valueOf(this.denum);
        }
    }

    public Rational resta(Rational op) {
        return this.suma(op.negado());
    }

    public Rational division(Rational op) {
        return this.producto(op.inverso());
    }
}
